/*********************************************************************************
 * Software License Agreement (BSD License)
 * Copyright (c) 2012, Carlos D. Correa (info@ngraph.org)
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of netzen nor the
 *    names of its contributors may be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************************/
#include <string.h>
#include <stdio.h>
#include <math.h>
#include "node.h"
#include <algorithm>
#include <assert.h>

Node::Node(const char *label): PropertyBag("Node",label) {
  setLabel(string(label));
  setSelected(false);
  setVisible(true);

  implicitEdges = 0;
  sizeImplicit = 0;
  index = -1;
}

bool Node::operator==(Node &b) {
  return index==b.index;
}

bool Node::operator==(int idx) {
  return index==idx;
}

Node::~Node() {
  for(unsigned int i=0;i<edges.size();i++) {
    delete edges[i];
  }
  destroyImplicitEdges();
  //print("Destroy node\n");
}

int Node::getIndex() {
  return index;
}

void Node::setIndex(int idx) {
  index = idx;
}

void Node::setSize(float r) {
  this->size = r;
}

float Node::getSize() {
  return size;
}

void Node::setLabel(string label) {
  this->label = label;
}

string Node::getLabel() {
  return label;
}

void Node::setSelected(bool value) {
  this->selected = value;
}

bool Node::isSelected() {
  return selected;
}

void Node::setVisible(bool visible) {
  this->visible = visible;
}

bool Node::isVisible() {
  return visible;
}

int Node::findEdge(Node *n) {
  for(unsigned int i=0;i<edges.size();i++) {
    if(edges[i]->getNode1()==n) {
      return i;
    }
  }
  return -1;
}

Edge * Node::getEdge(int idx) {
  for(unsigned int i=0;i<edges.size();i++) {
    if(edges[i]->getNode1()->getIndex()==idx) {
      return edges[i];
    }
  }
  return 0;
}

Edge * Node::addEdge(Node *n) {
  //if(label=="432") 
  //printf("ID = %s Adding neighbor %d\n", label.c_str(), i);
  int k = findEdge(n);
  if(k==-1)  {
    Edge *e = new Edge();
    e->setNode0(this);
    e->setNode1(n);
    e->setPropertyFloat("Multiplicity", 1);
    edges.push_back(e);
    return e;
  } else {
    int m = edges[k]->getPropertyFloat("Multiplicity");
    edges[k]->setPropertyFloat("Multiplicity", m+1);
    return edges[k];
  }
}

void Node::createImplicitEdges(int N, vector<Node*> nodes) {
  sizeImplicit = N;
  if(!implicitEdges) {
    implicitEdges = new Edge*[N];
    for(int i=0;i<N;i++) {
      addImplicitEdge(nodes[i]);
    }
  }
}

Edge * Node::addImplicitEdge(Node *n) {
  assert(n->getIndex()>=0 && n->getIndex()<sizeImplicit);
  Edge *e = new Edge();
  e->setNode0(this);
  e->setNode1(n);
  implicitEdges[n->getIndex()]=e;
  return e;
}

void Node::destroyImplicitEdges() {
  for(int i=0;i<sizeImplicit;i++) {
    delete implicitEdges[i];
  }
  delete implicitEdges;
}

Edge *Node::getImplicitEdge(int k) {
  assert(k>=0 && k<sizeImplicit);
  return implicitEdges[k];
}

bool Node::hasEdge(int j) {
  for(unsigned int i=0;i<edges.size();i++) {
    if(edges[i]->getNode1()->getIndex()==j) {
      return true;
    }
  }
  return false;
}

